summaryrefslogtreecommitdiff
path: root/storage/myisammrg
diff options
context:
space:
mode:
authorMikael Ronstrom <mikael@mysql.com>2009-06-11 12:07:59 +0200
committerMikael Ronstrom <mikael@mysql.com>2009-06-11 12:07:59 +0200
commit506c7fd47dd28e5726852e47d117bfbb37677005 (patch)
tree796cc97d1d103e18e0672d9b57dee4c54857073c /storage/myisammrg
parent4557f4ee9e9975966be6fa7c4fa553b30992ca6d (diff)
parentfbb96b339ae5fcce19446fd27a2fb75e49b960f8 (diff)
downloadmariadb-git-506c7fd47dd28e5726852e47d117bfbb37677005.tar.gz
Merge MySQL 5.1.35 into MySQL 5.4
Diffstat (limited to 'storage/myisammrg')
-rw-r--r--storage/myisammrg/ha_myisammrg.cc102
-rw-r--r--storage/myisammrg/ha_myisammrg.h2
-rw-r--r--storage/myisammrg/myrg_open.c5
3 files changed, 96 insertions, 13 deletions
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index 999dcf00b93..492bc15f749 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -117,7 +117,7 @@ static handler *myisammrg_create_handler(handlerton *hton,
*/
ha_myisammrg::ha_myisammrg(handlerton *hton, TABLE_SHARE *table_arg)
- :handler(hton, table_arg), file(0)
+ :handler(hton, table_arg), file(0), is_cloned(0)
{}
@@ -138,7 +138,8 @@ extern int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
extern int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
uint t1_keys, uint t1_recs,
MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
- uint t2_keys, uint t2_recs, bool strict);
+ uint t2_keys, uint t2_recs, bool strict,
+ TABLE *table_arg);
static void split_file_name(const char *file_name,
LEX_STRING *db, LEX_STRING *name);
@@ -219,7 +220,7 @@ static int myisammrg_parent_open_callback(void *callback_param,
TABLE_LIST *child_l;
const char *db;
const char *table_name;
- uint dirlen;
+ size_t dirlen;
char dir_path[FN_REFLEN];
DBUG_ENTER("myisammrg_parent_open_callback");
@@ -414,7 +415,28 @@ int ha_myisammrg::open(const char *name, int mode __attribute__((unused)),
/* retrieve children table list. */
my_errno= 0;
- if (!(file= myrg_parent_open(name, myisammrg_parent_open_callback, this)))
+ if (is_cloned)
+ {
+ /*
+ Open and attaches the MyISAM tables,that are under the MERGE table
+ parent, on the MyISAM storage engine interface directly within the
+ MERGE engine. The new MyISAM table instances, as well as the MERGE
+ clone itself, are not visible in the table cache. This is not a
+ problem because all locking is handled by the original MERGE table
+ from which this is cloned of.
+ */
+ if (!(file= myrg_open(table->s->normalized_path.str, table->db_stat,
+ HA_OPEN_IGNORE_IF_LOCKED)))
+ {
+ DBUG_PRINT("error", ("my_errno %d", my_errno));
+ DBUG_RETURN(my_errno ? my_errno : -1);
+ }
+
+ file->children_attached= TRUE;
+
+ info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
+ }
+ else if (!(file= myrg_parent_open(name, myisammrg_parent_open_callback, this)))
{
DBUG_PRINT("error", ("my_errno %d", my_errno));
DBUG_RETURN(my_errno ? my_errno : -1);
@@ -423,6 +445,55 @@ int ha_myisammrg::open(const char *name, int mode __attribute__((unused)),
DBUG_RETURN(0);
}
+/**
+ Returns a cloned instance of the current handler.
+
+ @return A cloned handler instance.
+ */
+handler *ha_myisammrg::clone(MEM_ROOT *mem_root)
+{
+ MYRG_TABLE *u_table,*newu_table;
+ ha_myisammrg *new_handler=
+ (ha_myisammrg*) get_new_handler(table->s, mem_root, table->s->db_type());
+ if (!new_handler)
+ return NULL;
+
+ /* Inform ha_myisammrg::open() that it is a cloned handler */
+ new_handler->is_cloned= TRUE;
+ /*
+ Allocate handler->ref here because otherwise ha_open will allocate it
+ on this->table->mem_root and we will not be able to reclaim that memory
+ when the clone handler object is destroyed.
+ */
+ if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
+ {
+ delete new_handler;
+ return NULL;
+ }
+
+ if (new_handler->ha_open(table, table->s->normalized_path.str, table->db_stat,
+ HA_OPEN_IGNORE_IF_LOCKED))
+ {
+ delete new_handler;
+ return NULL;
+ }
+
+ /*
+ Iterate through the original child tables and
+ copy the state into the cloned child tables.
+ We need to do this because all the child tables
+ can be involved in delete.
+ */
+ newu_table= new_handler->file->open_tables;
+ for (u_table= file->open_tables; u_table < file->end_table; u_table++)
+ {
+ newu_table->table->state= u_table->table->state;
+ newu_table++;
+ }
+
+ return new_handler;
+ }
+
/**
@brief Attach children to a MERGE table.
@@ -526,7 +597,7 @@ int ha_myisammrg::attach_children(void)
if (check_definition(keyinfo, recinfo, keys, recs,
u_table->table->s->keyinfo, u_table->table->s->rec,
u_table->table->s->base.keys,
- u_table->table->s->base.fields, false))
+ u_table->table->s->base.fields, false, NULL))
{
DBUG_PRINT("error", ("table definition mismatch: '%s'",
u_table->table->filename));
@@ -614,9 +685,10 @@ int ha_myisammrg::close(void)
DBUG_ENTER("ha_myisammrg::close");
/*
Children must not be attached here. Unless the MERGE table has no
- children. In this case children_attached is always true.
+ children or the handler instance has been cloned. In these cases
+ children_attached is always true.
*/
- DBUG_ASSERT(!this->file->children_attached || !this->file->tables);
+ DBUG_ASSERT(!this->file->children_attached || !this->file->tables || this->is_cloned);
rc= myrg_close(file);
file= 0;
DBUG_RETURN(rc);
@@ -824,6 +896,16 @@ int ha_myisammrg::info(uint flag)
table->s->crashed= 1;
#endif
stats.data_file_length= mrg_info.data_file_length;
+ if (mrg_info.errkey >= (int) table_share->keys)
+ {
+ /*
+ If value of errkey is higher than the number of keys
+ on the table set errkey to MAX_KEY. This will be
+ treated as unknown key case and error message generator
+ won't try to locate key causing segmentation fault.
+ */
+ mrg_info.errkey= MAX_KEY;
+ }
errkey= mrg_info.errkey;
table->s->keys_in_use.set_prefix(table->s->keys);
stats.mean_rec_length= mrg_info.reclength;
@@ -984,7 +1066,7 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
static void split_file_name(const char *file_name,
LEX_STRING *db, LEX_STRING *name)
{
- uint dir_length, prefix_length;
+ size_t dir_length, prefix_length;
char buff[FN_REFLEN];
db->length= 0;
@@ -1057,7 +1139,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
const char **table_names, **pos;
TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first;
THD *thd= current_thd;
- uint dirlgt= dirname_length(name);
+ size_t dirlgt= dirname_length(name);
DBUG_ENTER("ha_myisammrg::create");
/* Allocate a table_names array in thread mem_root. */
@@ -1116,7 +1198,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
void ha_myisammrg::append_create_info(String *packet)
{
const char *current_db;
- uint db_length;
+ size_t db_length;
THD *thd= current_thd;
MYRG_TABLE *open_table, *first;
diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h
index 4e7ddebb836..21d41c9d75a 100644
--- a/storage/myisammrg/ha_myisammrg.h
+++ b/storage/myisammrg/ha_myisammrg.h
@@ -25,6 +25,7 @@
class ha_myisammrg: public handler
{
MYRG_INFO *file;
+ my_bool is_cloned; /* This instance has been cloned */
public:
TABLE_LIST *next_child_attach; /* next child to attach */
@@ -60,6 +61,7 @@ class ha_myisammrg: public handler
int open(const char *name, int mode, uint test_if_locked);
int attach_children(void);
int detach_children(void);
+ virtual handler *clone(MEM_ROOT *mem_root);
int close(void);
int write_row(uchar * buf);
int update_row(const uchar * old_data, uchar * new_data);
diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c
index 64b4be2b7ca..14ba2853b22 100644
--- a/storage/myisammrg/myrg_open.c
+++ b/storage/myisammrg/myrg_open.c
@@ -33,7 +33,6 @@
myrg_attach_children(). Please duplicate changes in these
functions or make common sub-functions.
*/
-/* purecov: begin deadcode */ /* not used in MySQL server */
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
{
@@ -198,7 +197,6 @@ err:
my_errno=save_errno;
DBUG_RETURN (NULL);
}
-/* purecov: end */
/**
@@ -428,10 +426,11 @@ int myrg_attach_children(MYRG_INFO *m_info, int handle_locking,
if (!m_info->rec_per_key_part)
{
if(!(m_info->rec_per_key_part= (ulong*)
- my_malloc(key_parts * sizeof(long), MYF(MY_WME|MY_ZEROFILL))))
+ my_malloc(key_parts * sizeof(long), MYF(MY_WME))))
goto err; /* purecov: inspected */
errpos= 1;
}
+ bzero((char*) m_info->rec_per_key_part, key_parts * sizeof(long));
}
/* Add MyISAM table info. */