1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

WL# 2094 Federated Storage Handler

This changeset/patch is on top of changesets 1.1814 and 1.1846 
(for bugs 8033 and 8065) and now fixes bug 8535.

These changes have been built and tested successfully on build.mysql.com

handler.cc:
  Added hooks for federated_db_init() and federated_db_end(), 
  as done with ha_archive_db does, per suggestion by Ingo in
  code review of patch 1.1846.
ha_federated.h:
  declaration of federated_db_init() and federated_db_end()
ha_federated.cc:
  - Fixed some indentation problems from indent-ex (mainly to do with
    cases where "variablename += value"
  - Added federated_db_init() and federated_db_end(), as done with
    archive, which also handler more elegantly one of the memory leaks
    from bug 8033 where the federated_mutex was not freed
  - Removed extrenous debug messages in parse_url()
  - Fixed bug 8535, caused by NULL being quoted in write_row. This used to
    work (incorrectly) but a recent change was made in the server that 
    exposed this
This commit is contained in:
patg@krsna.patg.net
2005-02-16 23:07:10 -08:00
parent 986e122303
commit 005deef102
3 changed files with 125 additions and 101 deletions

View File

@ -372,6 +372,49 @@ static byte *federated_get_key(FEDERATED_SHARE *share, uint *length,
return (byte*)share->table_name; return (byte*)share->table_name;
} }
/*
Initialize the federated handler.
SYNOPSIS
federated_db_init()
void
RETURN
FALSE OK
TRUE Error
*/
bool federated_db_init()
{
federated_init= 1;
VOID(pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST));
return (hash_init(&federated_open_tables, system_charset_info, 32, 0, 0,
(hash_get_key) federated_get_key, 0, 0));
}
/*
Release the federated handler.
SYNOPSIS
federated_db_end()
void
RETURN
FALSE OK
*/
bool federated_db_end()
{
if (federated_init)
{
hash_free(&federated_open_tables);
VOID(pthread_mutex_destroy(&federated_mutex));
}
federated_init= 0;
return FALSE;
}
/* /*
Parse connection info from table->s->comment Parse connection info from table->s->comment
@ -425,9 +468,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
share->scheme[share->username - share->scheme]= '\0'; share->scheme[share->username - share->scheme]= '\0';
if (strcmp(share->scheme, "mysql") != 0) if (strcmp(share->scheme, "mysql") != 0)
{ {
DBUG_PRINT("ha_federated::parse_url",
("The federated handler currently only supports connecting\
to a MySQL database!!!\n"));
my_error(error_num, MYF(0), my_error(error_num, MYF(0),
"ERROR: federated handler only supports remote 'mysql://' database"); "ERROR: federated handler only supports remote 'mysql://' database");
DBUG_RETURN(1); DBUG_RETURN(1);
@ -447,8 +487,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
// make sure there isn't an extra / or @ // make sure there isn't an extra / or @
if ((strchr(share->password, '/') || strchr(share->hostname, '@'))) if ((strchr(share->password, '/') || strchr(share->hostname, '@')))
{ {
DBUG_PRINT("ha_federated::parse_url",
("this connection string is not in the correct format!!!\n"));
my_error(error_num, MYF(0), my_error(error_num, MYF(0),
"this connection string is not in the correct format!!!\n"); "this connection string is not in the correct format!!!\n");
DBUG_RETURN(1); DBUG_RETURN(1);
@ -467,8 +505,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
// make sure there isn't an extra / or @ // make sure there isn't an extra / or @
if ((strchr(share->username, '/')) || (strchr(share->hostname, '@'))) if ((strchr(share->username, '/')) || (strchr(share->hostname, '@')))
{ {
DBUG_PRINT("ha_federated::parse_url",
("this connection string is not in the correct format!!!\n"));
my_error(error_num, MYF(0), my_error(error_num, MYF(0),
"this connection string is not in the correct format!!!\n"); "this connection string is not in the correct format!!!\n");
DBUG_RETURN(1); DBUG_RETURN(1);
@ -496,8 +532,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
} }
else else
{ {
DBUG_PRINT("ha_federated::parse_url",
("this connection string is not in the correct format!!!\n"));
my_error(error_num, MYF(0), my_error(error_num, MYF(0),
"this connection string is not in the correct format!!!\n"); "this connection string is not in the correct format!!!\n");
DBUG_RETURN(1); DBUG_RETURN(1);
@ -505,8 +539,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
} }
else else
{ {
DBUG_PRINT("ha_federated::parse_url",
("this connection string is not in the correct format!!!\n"));
my_error(error_num, MYF(0), my_error(error_num, MYF(0),
"this connection string is not in the correct format!!!\n"); "this connection string is not in the correct format!!!\n");
DBUG_RETURN(1); DBUG_RETURN(1);
@ -514,8 +546,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
// make sure there's not an extra / // make sure there's not an extra /
if ((strchr(share->table_base_name, '/'))) if ((strchr(share->table_base_name, '/')))
{ {
DBUG_PRINT("ha_federated::parse_url",
("this connection string is not in the correct format!!!\n"));
my_error(error_num, MYF(0), my_error(error_num, MYF(0),
"this connection string is not in the correct format!!!\n"); "this connection string is not in the correct format!!!\n");
DBUG_RETURN(1); DBUG_RETURN(1);
@ -533,12 +563,13 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
DBUG_PRINT("ha_federated::parse_url", DBUG_PRINT("ha_federated::parse_url",
("scheme %s username %s password %s \ ("scheme %s username %s password %s \
hostname %s port %d database %s tablename %s\n", share->scheme, share->username, share->password, share->hostname, share->port, share->database, share->table_base_name)); hostname %s port %d database %s tablename %s\n",
share->scheme, share->username, share->password,
share->hostname, share->port, share->database,
share->table_base_name));
} }
else else
{ {
DBUG_PRINT("ha_federated::parse_url",
("this connection string is not in the correct format!!!\n"));
my_error(error_num, MYF(0), my_error(error_num, MYF(0),
"this connection string is not in the correct format!!!\n"); "this connection string is not in the correct format!!!\n");
DBUG_RETURN(1); DBUG_RETURN(1);
@ -546,8 +577,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
} }
else else
{ {
DBUG_PRINT("ha_federated::parse_url",
("this connection string is not in the correct format!!!\n"));
my_error(error_num, MYF(0), my_error(error_num, MYF(0),
"this connection string is not in the correct format!!!\n"); "this connection string is not in the correct format!!!\n");
DBUG_RETURN(1); DBUG_RETURN(1);
@ -575,32 +604,24 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
*/ */
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)
{ {
unsigned long *lengths; ulong *lengths;
unsigned int num_fields; uint num_fields;
unsigned int x= 0; uint x= 0;
DBUG_ENTER("ha_federated::convert_row_to_internal_format"); DBUG_ENTER("ha_federated::convert_row_to_internal_format");
num_fields= mysql_num_fields(result); num_fields= mysql_num_fields(result);
lengths= (unsigned long*) my_malloc(num_fields * sizeof(unsigned long), lengths= (ulong*) my_malloc(num_fields * sizeof(ulong),
MYF(0)); MYF(0));
cli_fetch_lengths((unsigned long*) (lengths), row, num_fields); cli_fetch_lengths((ulong*) (lengths), row, num_fields);
memset(record, 0, table->s->null_bytes); memset(record, 0, table->s->null_bytes);
for (Field **field= table->field; *field; field++, x++) for (Field **field= table->field; *field; field++, x++)
{ {
if (!row[x]) if (!row[x])
{
(*field)->set_null(); (*field)->set_null();
}
else else
/*
changed system_charset_info to default_charset_info because
testing revealed that german text was not being retrieved properly
*/
DBUG_PRINT("ha_federated::convert_row_to_internal_format",
("row[%d] %s length %lu", x, row[x], lengths[x]));
(*field)->store(row[x], lengths[x], &my_charset_bin); (*field)->store(row[x], lengths[x], &my_charset_bin);
} }
my_free((gptr) lengths, MYF(0)); my_free((gptr) lengths, MYF(0));
@ -637,9 +658,10 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info,
if (*key++) if (*key++)
{ {
if (to->append("IS NULL", 7)) if (to->append("IS NULL", 7))
DBUG_RETURN(1);
DBUG_PRINT("ha_federated::create_where_from_key", DBUG_PRINT("ha_federated::create_where_from_key",
("NULL type %s", to->c_ptr_quick())); ("NULL type %s", to->c_ptr_quick()));
DBUG_RETURN(1);
key_length-= key_part->store_length; key_length-= key_part->store_length;
key+= key_part->store_length - 1; key+= key_part->store_length - 1;
continue; continue;
@ -744,8 +766,10 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
uint table_name_length, table_base_name_length; uint table_name_length, table_base_name_length;
char *tmp_table_name, *tmp_table_base_name, *table_base_name, *select_query; char *tmp_table_name, *tmp_table_base_name, *table_base_name, *select_query;
// share->table_name has the file location - we want the actual table's /*
// name! share->table_name has the file location - we want the actual table's
name!
*/
table_base_name= (char*)table->s->table_name; table_base_name= (char*)table->s->table_name;
DBUG_PRINT("ha_federated::get_share", ("table_name %s", table_base_name)); DBUG_PRINT("ha_federated::get_share", ("table_name %s", table_base_name));
/* /*
@ -754,19 +778,6 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
do this. Since you will not want to do this, this is probably the next do this. Since you will not want to do this, this is probably the next
best method. best method.
*/ */
if (!federated_init)
{
/* Hijack a mutex for init'ing the storage engine */
pthread_mutex_lock(&LOCK_mysql_create_db);
if (!federated_init)
{
federated_init++;
VOID(pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST));
(void) hash_init(&federated_open_tables, system_charset_info, 32, 0, 0,
(hash_get_key) federated_get_key, 0, 0);
}
pthread_mutex_unlock(&LOCK_mysql_create_db);
}
pthread_mutex_lock(&federated_mutex); pthread_mutex_lock(&federated_mutex);
table_name_length= (uint) strlen(table_name); table_name_length= (uint) strlen(table_name);
table_base_name_length= (uint) strlen(table_base_name); table_base_name_length= (uint) strlen(table_base_name);
@ -819,7 +830,6 @@ error2:
pthread_mutex_destroy(&share->mutex); pthread_mutex_destroy(&share->mutex);
error: error:
pthread_mutex_unlock(&federated_mutex); pthread_mutex_unlock(&federated_mutex);
hash_delete(&federated_open_tables, (byte *) share);
if (share->scheme) if (share->scheme)
my_free((gptr) share->scheme, MYF(0)); my_free((gptr) share->scheme, MYF(0));
my_free((gptr) share, MYF(0)); my_free((gptr) share, MYF(0));
@ -837,15 +847,14 @@ static int free_share(FEDERATED_SHARE *share)
{ {
pthread_mutex_lock(&federated_mutex); pthread_mutex_lock(&federated_mutex);
if (!--share->use_count)
{
if (share->scheme) if (share->scheme)
my_free((gptr) share->scheme, MYF(0)); my_free((gptr) share->scheme, MYF(0));
if (!--share->use_count)
{
hash_delete(&federated_open_tables, (byte*)share); hash_delete(&federated_open_tables, (byte*)share);
hash_free(&federated_open_tables);
thr_lock_delete(&share->lock); thr_lock_delete(&share->lock);
pthread_mutex_destroy(&share->mutex); VOID(pthread_mutex_destroy(&share->mutex));
my_free((gptr) share, MYF(0)); my_free((gptr) share, MYF(0));
} }
pthread_mutex_unlock(&federated_mutex); pthread_mutex_unlock(&federated_mutex);
@ -900,7 +909,9 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked)
share->hostname, share->hostname,
share->username, share->username,
share->password, share->password,
share->database, share->port, NULL, 0)) share->database,
share->port,
share->socket, 0))
{ {
my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql)); my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql));
DBUG_RETURN(ER_CONNECT_TO_MASTER); DBUG_RETURN(ER_CONNECT_TO_MASTER);
@ -955,12 +966,9 @@ int ha_federated::close(void)
1 if NULL 1 if NULL
0 otherwise 0 otherwise
*/ */
inline uint field_in_record_is_null(TABLE * table, /* in: MySQL table inline uint field_in_record_is_null(TABLE *table, /* in: MySQL table object */
object */ Field *field, /* in: MySQL field object */
Field * field, /* in: MySQL field char *record) /* in: row in MySQL format */
object */
char *record) /* in: a row in MySQL
format */
{ {
int null_offset; int null_offset;
DBUG_ENTER("ha_federated::field_in_record_is_null"); DBUG_ENTER("ha_federated::field_in_record_is_null");
@ -1075,13 +1083,12 @@ int ha_federated::write_row(byte * buf)
("current query id %d field is not null query ID %d", ("current query id %d field is not null query ID %d",
current_query_id, (*field)->query_id)); current_query_id, (*field)->query_id));
(*field)->val_str(&insert_field_value_string); (*field)->val_str(&insert_field_value_string);
// quote these fields if they require it
(*field)->quote_data(&insert_field_value_string);
} }
// append the field name // append the field name
insert_string.append((*field)->field_name); insert_string.append((*field)->field_name);
// quote these fields if they require it
(*field)->quote_data(&insert_field_value_string);
// append the value // append the value
values_string.append(insert_field_value_string); values_string.append(insert_field_value_string);
insert_field_value_string.length(0); insert_field_value_string.length(0);
@ -1268,7 +1275,7 @@ int ha_federated::update_row(const byte * old_data, byte * new_data)
old_field_value.length(0); old_field_value.length(0);
} }
update_string.append(" WHERE "); update_string.append(" WHERE ");
update_string.append(where_string.ptr()); update_string.append(where_string.c_ptr_quick());
if (! has_a_primary_key) if (! has_a_primary_key)
update_string.append(" LIMIT 1"); update_string.append(" LIMIT 1");
@ -1606,10 +1613,10 @@ int ha_federated::rnd_pos(byte * buf, byte *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)); // pos /*
// is pos is not aligned
// not */
// aligned memcpy_fixed(&current_position, pos, sizeof(MYSQL_ROW_OFFSET));
result->current_row= 0; result->current_row= 0;
result->data_cursor= current_position; result->data_cursor= current_position;
DBUG_RETURN(rnd_next(buf)); DBUG_RETURN(rnd_next(buf));

View File

@ -174,3 +174,6 @@ public:
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); //required enum thr_lock_type lock_type); //required
}; };
bool federated_db_init(void);
bool federated_db_end(void);

View File

@ -364,6 +364,16 @@ int ha_init()
opt_using_transactions=1; opt_using_transactions=1;
} }
#endif #endif
#ifdef HAVE_FEDERATED_DB
if (have_federated_db == SHOW_OPTION_YES)
{
if (federated_db_init())
{
have_federated_db= SHOW_OPTION_DISABLED;
error= 1;
}
}
#endif
#ifdef HAVE_ARCHIVE_DB #ifdef HAVE_ARCHIVE_DB
if (have_archive_db == SHOW_OPTION_YES) if (have_archive_db == SHOW_OPTION_YES)
{ {
@ -405,6 +415,10 @@ int ha_panic(enum ha_panic_function flag)
if (have_ndbcluster == SHOW_OPTION_YES) if (have_ndbcluster == SHOW_OPTION_YES)
error|=ndbcluster_end(); error|=ndbcluster_end();
#endif #endif
#ifdef HAVE_FEDERATED_DB
if (have_federated_db == SHOW_OPTION_YES)
error|= federated_db_end();
#endif
#ifdef HAVE_ARCHIVE_DB #ifdef HAVE_ARCHIVE_DB
if (have_archive_db == SHOW_OPTION_YES) if (have_archive_db == SHOW_OPTION_YES)
error|= archive_db_end(); error|= archive_db_end();